home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-08 | 48.7 KB | 1,451 lines |
-
-
-
-
- szadb primer
-
-
-
- Michal Jaegermann
-
-
-
- edited by
-
- Anthony Howe
-
-
- 8 July 1991
-
-
-
-
- (this line printer approximation produced by dvi2tty and slightly edited)
-
-
-
-
- There is NO WARRANTY with respect to this publication, or the
- program it describes, and disclaim any implied or explicit suggestions
- of usefulness for any particular purpose. Use this program only if
- you are willing to assume all risks, and damages, if any, arising as a
- result, even if caused by negligence or other fault.
-
-
-
- Sozobon C compiler and szadb debugger are both copyright cfl1989
- by Sozobon Ltd. Both can be freely copied and distributed provided
- all copyright notices will remain intact and all modified versions will
- be clearly marked as such.
-
-
- Atari, ST, TOS and GEMDOS are trademarks of Atari Co.
- GEM is a trademark of Digital Research Co.
- Mark Williams C is a trademark or Mark Williams Co.
- Unix is a trademark of AT&T.
-
-
-
-
- 1 Introduction
-
-
- szadb is an assembly level debugger for programs written for
- the TOS operating system on the Atari ST computer. It is
- primarily meant to be a companion to the freely distributed
- Sozobon C compiler, and can be copied and passed around under
- the same conditions.
- One of design goals of the original szadb project was to
- provide a debugger closely resembling adb, which is available
- on most Unix systems. There are some dissimilarities which
- follow mostly from differences in target machines and
- operating systems. Still users with an adb experience should
- feel right at home.
- The originally released version 1.0 was written by Johann
- Ruegg and Don Dugger. Expanded to version 1.2 in a joint
- effort of Anthony Howe and Michal l Jaegermann. Further
- development to version 1.4 by Michal l Jaegermann. A document
- describing version 1.2 was prepared by Anthony Howe and
- Micha l Jaegermann. Modified slightly by the last author to
- reflect changes in versions 1.3 and 1.4
- Version 1.2 introduced multi-command input lines, which could
- be attached to breakpoints and stepping commands. Other it
- features included recording of a debugging sesion in a file,
- definitions function keys, and other assorted niceties. In
- addition to original Sozobon C symbols (Alcyon C style, also a
- default for ST version of gcc compiler) it also accepted the
- symbol table formats from Mark Williams C.
- Version 1.3, not very widely distributed, added to this list a
- "GST extension" of a symbol table format, with symbols up to
- twenty two characters long. Executables with such tables are
- produced by newer versions of gcc (ST) loader with -G option
- to the compiler.
- Version 1.4 brings much greater flexibility in supported
- screen displays. In particular it is possible now to run
- szadb in all six TT resolutions. Moniterm, in a tandem with a
- standard ST monitor, also can be used in a particularly
- convenient manner.
- If your compiler's symbol table format is not supported, or
- there are other changes or additions you wish to add, the
-
-
-
- 1
-
-
-
-
- complete source is provided free with the debugger.
- The document you are reading now serves as a gentle
- introduction to "adb way of debugging". It gives expanded
- explanations and examples but it does not cover all points
- described in a formal szadb description. Read the other
- document in any case!
-
-
-
- 2 First steps
-
-
- 2.1 Starting
-
-
- It is possible to run szadb either from a desktop or from a
- text shell, in either low, medium or high resolution. In this
- tutorial we will assume that szadb was launched from a command
- line on a screen 80 characters wide (this setting affects only
- the layout of some displays) and that the executable is called
- adb.ttp, in tribute to its older brother.
- The simplest way of starting szadb is to type something
- similar to
-
-
- adb.ttp program.ext
-
-
- where program.ext is any executable. Note that the file
- extension (tos, ttp, prg) must be provided. For debugging
- purposes, it is preferable to compile your program with
- debugger information (symbol tables). For Sozobon pass the
- option -t to either cc or ld. It is possible to debug a
- program without this information but this is not a trivial
- task. This tutorial assumes that symbolic information is
- provided.
- For debugging purposes, it is much preferable not to strip off
- symbol tables. In this tutorial we will always assume that
- this was not done. To achieve that effect, while compiling
- with Sozobon C, pass -t flag to cc.
- If you do not have your favourite test program handy then you
- may compile from the provided sources and use for experiments
- a simplified version of unexpand.tos; it replaces, if
- possible, runs of white space from stdin with tabs and writes
- results on stdout. Further examples will use that program
-
-
-
- 2
-
-
-
-
- compiled by Sozobon C compiler, version 1.3, with -t and -O
- flags.
- Once the debugger is started you should see on your screen a
- display resembling the following:
-
-
- Szadb version 1.3mj+ach(english)
- >
-
-
- indicating that everything is in order. The character > is
- the prompt. Its presence is the most striking visual feature
- showing that we are not dealing with the "real" adb.
-
-
-
- 2.2 Where am I?
-
-
- If you hit at this moment <Return> key szadb should respond
- with
-
-
- __start:
-
-
- The debugger positioned itself at the very beginning of a
- loaded program. szadb "remebers" the last command and its
- current location, which is known as "dot". You may set
- "dot" by typing any valid expression which will evaluate to
- an address. Hitting <Return> by itself repeats the last typed
- in command (not the executed one! This distinction will be
- important later).
- In this version the "dot" is set to low TPA, or a starting
- execution address. The initial default command is /a which
- will print the symbolic value of "dot" followed by a colon.
- To see a numerical display of the "dot" try the following:
-
-
- .=X <Return>
-
-
- for a hexadecimal address, or
-
-
- .=D <Return>
-
-
- for the same one in a decimal form.
- A note for Unix hackers. In szadb there is no distinction
- objectspace and dataspace. Therefore prefixes ? and / in
- commands are equivalent. Typing ?a will cause the same effect
- as typing /a.
-
-
-
- 3
-
-
-
-
- Addresses are printed in a form symbol+offset, where possible.
- If there is no symbol table, or if offset is getting too big,
- you will notice that addresses are printed as hexadecimal
- values. The offset limit has initialy value of 0x400 but it
- can be changed by $s request, in the form
-
-
- <new_value>$s
-
-
- The default number base for commands and displays is sixteen
- (hexadecimal). Please refer to the documentation on how to
- change the default base and use numbers in other bases.
- White space, which is not a part of a literal string, is not
- significant in szadb requests as long as a total number of
- characters in the command line is below an input buffer length
- (78 for this version). <Return> always terminates a current
- line. Try adding some blanks and tabs to previously typed
- commands.
-
-
-
- 2.3 Disassembling
-
-
- Lets try something more exciting. A request for printing
- machine language instructons is /i. It may be preceded by a
- count. Try ,4/i. The comma is necessary and informs szadb
- that what follows is a number of times to repeat the request.
- If you will omit it then the debugger will decide that you
- want to start with a location 4. If all is well then szadb
- will respond
-
- __start:
- move.l sp,a5
- move.l 4(sp),a4
- move.l a4,__base
- move.l 8(a4),d3
-
-
-
- After this request a default command becomes /i. Therefore
- to see the next four locations it is enough to type ,4 and
- szadb will show
-
- > ,4
- __start+10:
- add.l c(a4),d3
-
-
-
- 4
-
-
-
-
- move.l d3,_etext
- move.l 10(a4),d3
- add.l 14(a4),d3
-
-
-
- Note that the "dot" has moved. This is a common feature of
- all memory examining requests. The "dot" will be set past
- all already scanned memory. If you want to look at the same
- memory area one more time, possibly using a different request,
- use & to reset your position. It is a shorthand for the last
- typed in address.
-
-
-
- 2.4 More on talking to szadb
-
-
- A general szadb command has a form
-
-
- address ,count request_with_its_modifiers
-
-
- where each of three parts is optional or possibly not used.
- Please refer to the documentation to see all available
- requests. For all practical purposes count 1 means forever.
- Read a little bit further before trying this.
- Display format modifiers can be concatenated together. For
- example, the following
-
-
- main,9/ai
-
-
- will print the first nine instructions, labelled by their
- addresses, starting from _main. Like this:
-
- _main: link a6,#-6
- _main+4: movem.l [d3-5],-(sp)
- _main+8: move.l #_tabs,-(sp)
- _main+e: bsr _settab
- _main+12: addq.w #4,sp
- _main+14: clr.w d5
- _main+16: clr.w d3
- _main+18: move.l #__iob,-(sp)
- _main+1e: jsr _fgetc
-
- Note that the leading underscore, required to produce an
- internal form of a symbol main was prepended automatically.
-
-
-
- 5
-
-
-
-
- To get to an address of __main, if such symbol in your program
- exists, you have to type its name in full. Similar but
- slightly different rules will be in force if your program has
- a symbol table in the MWC format.
- If you do not know which symbols are available issue a request
- $e. A display similar to the following will start to scroll
- accross your screen.
-
- > $e
- __start: 77812
- __exit: 778da
- _gemdos: 778e2
- _bios: 778ec
- _xbios: 778f6
- _bdos: 77900
- _main: 77954
- _settab: 77a72
- __main: 77aac
- _exit: 77b0c
- ................
-
- The general method to stop a scrolling screen for a moment is
- to use <^S> and any other key will continue. A <^C> will
- cancel the command and any further output. Starting with
- version 1.4 this includes also a paging. This means that
- display stops after showing one screenful of symbols and szadb
- waits for your keyboard input. Keys <q>, <Q> and <^C> break,
- any other key continues. A processing of the request is
- finished when you will get back a standard szadb prompt of "> ".
-
- Some hexadecimal numbers may look like symbols. For example,
- if you happen to have a symbol abba in your program then szadb
- will understand main+abba as a request for setting the "dot"
- to an address which is a sum of addresses of main and abba,
- even if you really meant an adress at offset of 0xabba from
- main. To avoid this misinterpretation it is enough to type
- main+0abba --- a number has a leading zero. It the symbol
- abba is not defined then the ambiguity does not arise.
- Assuming that the default base is sixteen abba will be taken
- as a number. Otherwise such expression will be not accepted
-
-
-
- 6
-
-
-
-
- and you will see only an error message. The form 0xabba has a
- unique meaning and always works.
-
-
-
- 3 Running under szadb
-
-
- 3.1 How to run | with arguments
-
-
- To run a loaded program, with a name passed as a szadb
- argument, one has to type :c, which is a short for :continue.
- When the program is running szadb switches to the program
- screen which is different from that one used by the debugger.
- In particular, all program keyboard input will be accepted
- from the program screen. Unfortunately there is no way, at
- least not in this version, to read the debugged program
- standard input from a file. It has to be typed in. To switch
- from the szadb screen the program window use <^W> and return
- from the visit with any other character.
- The program itself may have arguments. In principle there are
- two methods with which they can be set. Firstly, you may
- specify them when starting szadb. Everything which follows
- the name of a loaded executable will be taken as its arguments
- and copied verbatim to its basepage. A request $p will
- display the whole basepage and it will allow you to check if
- you really got what you expected. szadb does not allow for
- any argument extending schemes and it will trunctate command
- lines which are too long.
- The second method allows you to specify arguments as an
- optional tail of :c request. Once arguments were set, by any
- of these methods, they cannot be changed and further attempts
- to do so will be ignored.
- Since both shell command lines and the input line inside of
- szadb are limited in length, and partially already taken, it
- may appear that there is no way to fill all available basepage
- space with program arguments by any method, short of writing
- directly to a computer memory. As we will see later this is
- not true, even if it requires a little bit of trickery. (See
- further descriptions how to define and execute function keys.)
- When you are ready to quit, because you are done or lost and
- wish to start afresh, enter $q. If the debugee process exited
- of its own accord then szadb will terminate too.
-
-
-
- 7
-
-
-
-
- 3.2 Setting breakpoints
-
-
- Executing a program under a debugger is of no great use
- without breakpoints. Here is the simplest way in which they
- can be set.
-
-
- main:b
-
-
- We can do even better than that. Try
-
-
- main:b ="My first szadb breakpoint"n;.=XD;,8/ai
-
-
- Everything which follows :b on the input line will be stored
- and executed later on when the breakpoint is hit. Multiple
- commands are separated by semicolons. By the way, you may use
- semi-colons for immediate requests too.
- Breakpoints also can have counts. Using as an example
- unexpand.tos, and a fragment of its disassembled code shown in
- a previous section, we may set a breakpoint
-
-
- main+18,3:b="about to read"n
-
-
- in a main loop of this program, just before fgetc() is called.
- With this count an execution will stop only for every third
- character to be accepted.
- Setting a breakpoint on the top of an existing one is allowed
- and it will simply cause a replacement --- changing possibly a
- count and commands to execute. A list of all current
- breakpoints, with their counts and associated commands, is
- produced by the $b request. Information shown at the bottom
- of this list will be explained later.
- It is not the best idea to set a breakpoint somewhere between
- two program instructions. Nothing terrible will happen
- immediately, but your debugging run may end up prematurely
- amid an utter confusion. Sometimes it is possible to restart
- a wayward program by writing a needed address directly into a
- program counter with a address>pc request, but this is not
- guaranteed to work. It is also advisable to keep breakpoints
- on an execution path. They are a limited resource and there
- is no point wasting it.
-
-
-
-
-
- 8
-
-
-
-
- 3.3 Displaying information
-
-
- szadb provides many ways to display information about the
- state of your program. Some of these requests were detailed
- above. Another is $r, which will show the contents of all
- registers and status flags. If you are interested in an
- individual register then use something like
-
-
- <a0=X
-
-
- Replacing above = with /, or ?, will bring a hexadecimal
- display of the long word stored at the location pointed to by
- register a0. Careful here, the last form will move the
- "dot". There are many other possible formats. Try, for
- example, main,20/x and <b,2/s .
- The second example uses one of four read-only variables
- provided by szadb, which are
-
-
- l lowest text address
- t length of the text segment
- b start of the bbs segment
- d length of the data segment
-
-
- With an exception of l names follow the Unix convention. They
- will be particulary handy if you will have a misfortune of
- debugging executable without a symbol table.
- Formats in requests can be combined. Let us try something
- like follows.
-
-
- ="Text memory dump"2n;main,<b-main%8+1/4x4^rr|rr8cn
-
-
- and here are initial lines of a resulting display, where "."
- replaces all non-printable characters.
-
- Text memory dump
-
-
- _main:
- 4e56 fffa 48e7 1c00 | NV..H...
- 2f3c 6 8ae6 6100 | /<....a.
- 10e 584f 4245 4243 | ..XOBEBC
- 2f3c 6 88a0 4eb9 | /<....N.
- 6 7c40 584f 3800 | ..|@XO8.
-
-
-
- 9
-
-
-
-
- b87c ffff 6706 b87c | .|..g..|
- 4 6612 4267 4eb9 | ..f.BgN.
- 6 77d6 544f 4cdf | ..w.TOL.
-
-
-
- Note that division is denoted by a % character and that 8
- divides a difference <b-main and not only main, since all
- expressions are evaluated in strict left-to-right order.
- Let's break down the format modifiers to see what is actually
- happening
-
-
- 4x print four short words in hex,
- 4^ backup the "dot" by four current fields
- (short words),
- rr|rr print 2 blanks, vertical bar, and 2 more
- blanks,
- 8c print 8 characters,
- n and a newline.
-
-
- Displays that are wider then a current screen width (40 or 80)
- will have lines split automatically.
-
-
-
- 3.4 Recording your session
-
-
- A request $>filename starts writing a transcript of everything
- which shows on your screen to the file filename. All examples
- longer than a couple of lines were prepared this way. If the
- filename is missing then the currently opened transcript will
- be closed. The output is always appended to the given file,
- so that it is possible to open, close, and re-open the same
- file any number of times.
- Because GEMDOS is not re-entrant it is not a very very good
- idea to perform an actual file write while processing a GEMDOS
- call. It is nearly certain you will crash your system. The
- safest course in such spots is to turn recording temporarily
- off. However, transcript output is buffered by default, so
- actual writes occur only when the buffer is flushed when full
- or because the file was closed. Therefore with proper care,
- one can empty the buffer prior to dangerous spots and even
- create a record of a GEMDOS call, provided it is not too
-
-
-
- 10
-
-
-
-
- wordy. A handy definition for a function key to do this is
- $>;$> (see the last section on function keys).
- It is advisable not to write files to your hard drive, instead
- use a RAM drive or a dedicated floppy (which can be
- reformatted in case of disaster). Remember that a buggy
- program and the debugger can write anywhere. Over system file
- buffers and cached File Allocation Tables as well.
- If you need all memory you can get it is possible to turn off
- transcript buffering with command line option -nb. But then
- you will have to be extremely careful about possible conflicts
- with GEMDOS.
- Note! After $>file request your default command is $> and not
- the last command you were executing previously. It is
- possible to execute $> inadvertently by hitting <Return> or by
- making some mistake while typing the next line. This will
- close your transcript with obvious results. When something
- like thats happens, or when in doubt, issue another $>file.
-
-
-
- 4 Bug hunting
-
-
- 4.1 Compiling for szadb
-
-
- Lets have a closer look at the C program below. Its stated
- purpose is to replace, if possible, runs of white space with
- tabs. The width of a tab is fixed and equal to a constant
- TABSTOP. If a text line is getting too long then substitutions
- are abandoned and remaining characters are copied without
- modifications.
-
-
- #include <stdio.h>
-
-
- #define MAXLIN 132
- #define TABSTOP 8
- 5
- int tabs[MAXLIN];
-
-
- main ()
- {
- 10 int c, delay, col;
-
-
-
- 11
-
-
-
-
- void settab ();
-
-
- settab (tabs);
-
-
- 15 col = delay = 0;
- while (EOF != (c = getchar ())) {
- if (MAXLIN < col) {
- /* copy remaining characters on a line */
- do {
- 20 putchar (c);
- } while ('\n' != c &&
- EOF != (c = getchar ()));
- col = 0;
- }
- 25 else {
- switch (c) {
- case '\t':
- while (!tabs[col])
- col++;
- 30 case ' ': /* fallthrough */
- if (!tabs[col]) {
- col += 1;
- continue; /* keep delay */
- }
- 35 putchar ((delay == col) ? ' ' : '\t');
- col += 1;
- break;
- default:
- while (delay < col) {
- 40 putchar (' ');
- delay += 1;
- }
- putchar (c);
- col = ('\n' == c ? 0 : col + 1);
- 45 break;
- } /* switch */
- } /* if (MAXLIN < col) */
- delay = col;
- }
-
-
-
- 12
-
-
-
-
- 50 exit (0);
- }
-
-
- void
- settab (tab_pt)
- 55 short *tab_pt;
- {
- int i;
-
-
- for (i = 0; i < MAXLIN; i++) {
- 60 *tab_pt++ = (0 == (i % TABSTOP));
- }
- }
-
-
- This program has actually two bugs. See if you can find them
- just examinig the source.
- Here is how szadb can help. Compile source as follows (these
- commands are for Sozobon C)
-
-
- cc -t -O -o unexpand.tos unexpand.c
-
-
- Flag -O is not necessary but with this particular compiler you
- will probably find a disassembled code easier to follow. You
- may test the compiled executable on its own source.
-
-
- unexpand.tos <unexpand.c >output
-
-
- In the first moment the program appears to work, but a closer
- examination of the output reveals that the indentation is not
- exactly right. Moreover, some lines start with a blank,
- followed by a tab, which is not really what was intended.
- There are also other problems. Check yourself. The likely
- suspect will be an array tabs of tabstops filled by a function
- settab().
-
-
-
- 4.2 The first bug
-
-
- Start the program under szadb control
-
-
- adb.ttp unexpand.tos
-
-
-
- 13
-
-
-
-
- and set a breakpoint at settab+4, just after link instruction.
- Run the program with :c ; $C. This will produce the following
- display
-
- break at _settab+4
- _settab+4: movem.l [d3-4],-(sp)
- _settab+4(0006,8bb4)
- _main+12(0001,0006,8cbe,0006,73a2)
- __main+4e(? at 69cc6)
-
- In the absence of better information all arguments shown in
- the stack backtrace are assumed to be two bytes wide. We know
- from the source that settab() actualy expects one pointer.
- Confirm that it got a right one by putting it together from
- two halfs and using the request 68bb4=p to print it as the
- symbol. You should see _tabs in response. To continue
- execution of the current function till it returns to its
- caller, use :f which stands for :finish.
- It is clear from lines 30 and 35 that the first tabstop in
- _tabs is expected to be on a position TABSTOP - 1 . Dumping
- some initial fragment of the just initialized array we see the
- following:
-
- > tabs,3/4x
- _tabs:
- 1 0 0 0
- 0 0 0 0
- 1 0 0 0
-
- This is clearly wrong and one bug becomes obvious. To repair
- it line 59 should be changed to
-
-
- for (i = 1; i <= MAXLIN; i++) {...}
-
-
-
- 4.3 ...and the other one
-
-
- The second bug is harder to spot, since for most of test
- inputs our program will work correctly. This is a typical
- example of a program broken for boundary conditions. To make
- it easier to track the problem set MAXLIN to some small
- integer (around 10 should be good), recompile the program,
- restart the debugging session and set a breakpoint at main+28,
-
-
-
- 14
-
-
-
-
- just after a character was read. Set this breakpoint with a
- count and a request to show a received character with
-
-
- main+28,5:b <d0=cx
-
-
- With carefuly chosen input this will show where you are in the
- program and will skip unnecessary stops in the same time. You
- have to provide an input by typing it yourself. Remember that
- to repeat the last command :c it is enough to hit <Return>.
- For execution defaults szadb will use the most recently typed
- command even if some other requests were executed by
- breakpoints.
- In order to see how the received character is processed you
- can single step with :s, which will follow program execution.
- The request :n will single step like :s but will execute
- function calls at full speed and so have the effect of
- stepping over them. Breakpoints set on skipped levels still
- will be obeyed.
- Tracing some tests inputs with the value of the variable col
- around MAXLIN should reveal the second error soon enough. If
- you want to try it yourself, do not read further.
- Looking at line 17 we find a sharp less-than inequality in the
- test. It should be replaced by a less-than-equal-to.
- Otherwise, when the value of col equals MAXLIN, and your input
- is "right", the program is trying to read, in lines 28 and 31,
- from the location &tabs[col], which is one past the end of the
- array. The remaining analysis of this bug is left as an
- exercise to the reader.
-
-
-
- 4.4 Breaking out
-
-
- Another stepping command is the :j jump request. Its purpose
- it to short-circuit loops. It behaves exactly like :n in that
- it skips-over function calls but unlike the :n request which
- follows branch instructions, the :j will place a temporary
- breakpoint at the instruction immediately following the
- current instruction in memory. Think of :n as
- step-next-logical instruction and :j as step-next-physical
- instruction. The idea is that you only use :j to step-out of
- loops where you are sitting on the loop-back branch.
-
-
-
- 15
-
-
-
-
- ...
- bra .test
- .body:
- ...
- .test:
- cmp d0, d1
- bnz .body
- .end
- ...
-
- In the example above, if you are sitting on the bnz
- instruction and you wish to execute the remainder of the loop
- at full speed then you use the :j, which places a temporary
- breakpoint at the location .end. However care must be taken
- when using this command because it is possible that the
- flow-of-control never reaches the temporary breakpoint.
-
- ...
- bra .snert
- .never:
- ... ; might be local data here
- .snert:
- rts
-
- This is a case where NOT to use the :j command. Basically to
- use the :j request you should know how your C compiler sets up
- its loops or where your assembler code is meant to go. It is
- sometime a good idea to put a safety breakpoint somewhere you
- know you will end up.
- Because of the unusual nature of the :j request, it will not
- autorepeat if the next command is just a <Return> key. Instead
- :n is performed. Also it is also considered a variant of :n
- when attaching execution requests to stepping commands (see
- further down).
- It should be also mentioned that all stepping commands have
- upper case counterparts, which are noisier. When used they
- return the a full register display after the step (:S is like
- doing :s;$r).
-
-
-
- 16
-
-
-
-
- 5 More fun and games
-
-
- This section covers some finer points of szadb use. You may
- put them aside when just starting first experiments with the
- debugger. But probably one day you will find some of that
- information very useful.
-
-
-
- 5.1 Advanced steps
-
-
- It was already mentioned that all stepping commands may have
- also attached szadb requests. As a matter of fact there is
- even one default, for :f. To get a similar effect for other
- steps just type what you want to be executed after a given
- command on the szadb input line. For example
-
-
- :s ="this string printed by :s command"n
-
-
- You will notice that this form of :step does not move you
- ahead in the program. This gives an opportunity to set and
- modify requests in advance, without an immediate execution.
- It also saves your nerves if you are not a very good typist.
- To really step by one instruction forward hit <Return> and
- observe what will happen. As noted before :j is a variant of
- :n and setting request for it will really change what is
- attached to :n.
- The example above is not tremendously useful, but tracking
- values of a chosen registers can be. Or anything else that
- you need and that will fit on the command line. This
- condition is much less limiting than it appears when used in
- conjunction with function keys.
- There are two points to remember. There is no syntax check
- while you are setting requests. Watch what you are typing if
- you do not want to see only error messages. And there is
- nothing to prevent a direct or indirect recursion. Since a
- depth of szadb stack is limited and <^C> does not always work
- it is better to avoid such constructs.
- If you came to a conclusion that the only way to change
- requests attached to a stepping command is to overtype them
- with something else then you are correct. Moreover an empty
- string is not a good replacement since it causes an execution.
-
-
-
- 17
-
-
-
-
- Luckily there is some other way to turn a noise off. Try
- typing ::s- and similar commands for :n and :f. Switched off
- requests are not gone, unless later redefined. They can be
- brought back by a similar command as above in which - was
- replaced with +. The default request for :f is special. It
- cannot be overtyped or turned on by ::f+. To bring it back
- use ::f` instead.
- There is one more way of request switching. If you will type,
- for example, ::n_, then whatever was attached to :s will be
- performed also for :n, instead of a "native" command. This
- gives an opportunity to create, say, a quite complicated
- request for :n and most of the time execute a simpler request
- for :s. When an original request for :n is needed it is
- enough to type ::n+ to get it back. The same mechanism works
- for :f, temporarily redirecting its requests "down" to the
- first active one. There is no similar switching going the
- other way. To gain a better understanding try all of this
- after defining various requests for each of stepping commands
- and examine effects with the $b command after every switch.
- It is also possible to make user breakpoint silent or not.
- For example
-
- main:b ="entering main"
-
- main::b- and main::b+ turns the action off and on.
-
-
-
- 5.2 How to use function keys
-
-
- Function keys can be defined, only once per debugging session,
- by reading their definitions from a file. The name of the
- file can be passed on the command line with -k filename. The
- file may be as simple as this
-
- # flush buffers of a transcript file record
- F1 $>;$>record
-
-
- F2 ="this is pretty long string which will be ins\
- erted when you will hit function key F2"n;
- F1 ="an attempt to redefine F1\n"
-
- Note that an uppercase F, which starts key definition, has to
- be in the first column and it has to be immediately followed
-
-
-
- 18
-
-
-
-
- by a valid key number. Shifed functions keys have numbers
- between 11 and 20. A definition of <F2> is continued on the
- next line since a terminating newline is escaped with a \
- character. Otherwise this continuation line would be simply
- ignored. szadb also does not pay any attention to the second
- definition of <F1>. To see a list of all function keys defined
- type $k.
- Defined function keys can be used in two ways. Just hitting a
- function key will insert into the current input line as many
- characters from a corresponding string as it will fit. The
- resulting input text can be edited. In order to execute a
- full definition use $k followed by a key number --- always in
- decimal. For example, a request $k2 will print twice the
- message, which was just defined in the function key file.
- Note that there no way to specify that a function key should
- execute immediately instead of waiting for a <Return>. Also is
- there no default function key file name like --- adb.key ---
- so you'll have to specify the -k file option on the command line
- each time or use a command alias. Note also that requests of
- a form $k<number> do not autorepeat.
- It is clear that strings of commands attached to function keys
- can be longer than a lenght of the input line. Actually
- around 2K will be accepted. This is hopefuly longer than any
- szadb script you ever want to write. Especially if you take
- into account that one script can call another. Warnings
- against recursion apply as well.
- Such long scripts can be, of course, attached to breakpoints
- or stepping commands. They give also, previously mentioned,
- opportunity to fill all available space on a base page with
- command line arguments. Just define one of function keys as
-
-
- :c <text to put on a base page>
-
-
- and execute at the beggining of your session. Coupled with a
- possibility of directly modifying the memory this allows for a
- preparation of scripts which will emulate any extended
- arguments scheme, even if szadb directly does not support
- directly any of these.
-
-
-
- 19
-
-
-
-
- 5.3 Other symbol table formats
-
-
- This debugger was designed as a companion for Sozobon C and
- therefore it understands its symbol table format, which was
- inherited from Alcyon compiler. The version for which this
- document was written also supports MWC --- currently the
- official Atari development compiler. It will cooperate also
- with the ST version of GNU compiler gcc. If you happen to
- have an older version of gcc loader it may be necessary for
- you to get your hands dirty in a source code. Even better
- idea would be to update your compiler. The current gcc loader
- can optionally produce symbol tables in "GST format" where
- symbols can be up to twenty two characters long. Version 1.3
- of szadb will correctly recognize and use that format as well.
-
-
-
- 5.3.1 Mark Williams C support
-
-
- Symbols created by MWC are outwardly different from those
- produced by Sozobon C in that that names can be longer --- up
- to sixteen characters --- and an underscore character is
- appended instead of beeing prepended. When szadb will detect
- an MWC produced object it will apply its conventions. That
- means that if you type main it will first try to find a symbol
- main. If this fails it will search for main_ next (not for
- _main). If a symbol name has a leading underscore, or more
- than one trailing, you have to type them yourself.
- The debugger is trying to guess by itself which compiler
- produced the current executable. If it guesses wrong you may
- always override its choice by dropping a hint on the command
- line. It consists of an -os flag for the Sozobon format and
- -om for MWC. Remember that if you work in an assembler the
- guessing code can always be fooled. The flags always provide
- a way to set things straight.
- When writing this guessing code I had no official description
- of the format used by MWC. All necessary information was
- inferred from an examination of MWC produced binaries. The
- code worked so far on everything I tried, but it may happen to
- be wrong for your version. Since szadb comes complete with
- source you can modify it accordingly and recompile (look for
-
-
-
- 20
-
-
-
-
- all places where a global variable swidth is modified).
-
-
-
- 5.3.2 How to work with gcc
-
-
- A default form of executables created by this compiler is with
- a symbol table attached. You need to use -s flag if you
- really do not want it produced. A default format for TOS
- version of this compiler is basically the same as for Sozobon
- C or Alcyon. If you happen to be an owner of an old version
- there is one subtle difference. A bit which carries an
- information that a symbol is global one, known as S_EXT in
- szadb parlance, is not set. This makes the debugger blind to
- a symbol presence.
- Here are instructions how to modify an old version of a file
- ld.c which contains sources for gcc linker. In a function
- write_atari_sym(p, str) for TOS version add the following
-
-
- if (p->n_type & N_EXT)
- sym.a_type |= A_GLOBL;
-
-
- just before a line which reads
-
-
- sym.a_value = p->n_value;
-
-
- Recompile and reinstall linker and from this moment on szadb
- recognizes gcc produced symbols.
- Even better idea would be to upgrade your compiler to a newer
- version. The modification described above will be already
- present, but there is more. Currently gcc, upon a presence of
- -G flag, may produce symbol tables with names up to twenty two
- characters long. Version 1.3 of szadb will correctly
- recognize such symbols making for much nicer debugging (even
- if this will require more typing from time to time).
- Internally this is a version of Sozobon format. Use -os flag
- in case of confusion.
- If for some reasons you cannot upgrade, you do not have linker
- sources or you cannot recompile them --- because you do not
- have enough memory, for example --- not everyting is lost. It
- is quite feasible to disable S_EXT check in setsym() (look in
- the file adb1.c). You will not notice any change for Sozobon
- C created executables. All symbols occuring in their symbol
-
-
-
- 21
-
-
-
-
- tables are actually always global. This is not quite true for
- gcc and some new, sometimes strange, symbols will appear but
- usually this will not create any problems. In order to have
- only globals in a gcc produced symbol table pass -x flag
- either to gcc or to its linker.
-
-
-
- 5.3.3 Command line interpretation
-
-
- As mentioned before szadb supports only "vanilla" command
- line without any extension schemes. Other compilers, like
- gcc, may expect something different and there could be some
- disagreements about an interpretation of a command line.
- Usually this can be fixed quite easily. Here is a file, named
- fixargs.adb, which can be used with a command line following
- this pattern
-
-
- szadb.ttp -k fixargs.adb <program> [argument, ...]
-
-
- where <program> was compiled by gcc.
-
- # an example of a function keys definition file used
- # to correct an argument interpretation for gcc
- # compiled program
- F1 $k11; $k13 ; $k14; $k15; $b; :c
- F11 main:b <sp,10/x; $k12
- F12 <sp/W *(<sp+4)-3; <sp+4/W *(<sp+8)+c; <sp,10/x
- # for 16 bit
- #F12 <sp/w *(<sp+2)-3; <sp+2/W *(<sp+6)+c; <sp,10/x
- F13 getitime:b
-
- This file defines some function keys. The fact that commands
- associated with keys <F14> and <F15> do not exist, even if they
- are referenced in a line for <F1>, is not harmful in any way.
- You may define these keys later for your advantage. After
- szadb started hit <F1> followed by <Return>. This will cause,
- among others, an execution of a command attached to <F11>, i.e
- <F1-shifted>. This command will set a breakpoint at a start of
- real program with a fixup command attached. In turn, this
- will modify your stack causing your program to see proper
- arguments. Requests in a form of <sp,10/x are added only for
- reassurance and to show what really happens.
-
-
-
- 22
-
-
-
-
- The example above assumes that a symbol getitime is defined in
- your program. Replace with something which is really present
- or you will see some error messages. They are not fatal. All
- of this is not going to work if main is not present in your
- symbol table. This is not really likely for a program which
- has a symbol table and was compiled from C sources, but may
- happen for other languages. Modify accordingly.
-
-
-
- 5.3.4 Other compilers
-
-
- If you own a compiler which produces symbolic information in
- an unsupported format you can modify szadb yourself to support
- it. For a model of how to do this look for setsym() and
- mwsetsym() in the file adb1.c. Both of them call addsym()
- which performs an actual insertion of a new symbol and its
- value into a linked list of supported symbols. A current
- version of addsym() will handle symbol names of any length but
- internally they will be chopped off to something not longer
- than the current value of the global variable swidth. Ensure
- that this value is set properly for your needs.
- The mechanism above can be easily extended to allow reading
- some symbols and their values from a user suplied text file.
- Some may find it very handy. The current version of szadb
- does not support this feature. It is possible to roll your
- own if you really need it.
-
-
-
- 5.3.5 Screens of not a standard ST size
-
-
- Starting with a version 1.4 szadb does not have standard ST
- screen parameters embedded into its code. Instead it reads
- all necessary information from line-A variables and reserves
- all needed buffers accordingly. In particular it follows that
- szadb will run correctly in all six TT resolutions. It may
- also work with different overscan utilities, provided screen
- geometry variables in a machine were updated properly. Note
- that fonts used are resolution dependent but fixed for a given
- resolution. This means that putting monochrome ST into 50
- line mode will not give nice results without code
- modifications (see w_init() in window.c).
-
-
-
- 23
-
-
-
-
- A special support is provided for Moniterm monitors. Because
- of limitations of a Moniterm driver you will need also a
- standard ST monitor connected in parallel. In such setup your
- program screen will be displayed on Moniterm and szadb will
- print its information to a side monitor; no screen flipping
- with <^W> is needed or possible.
- Since the debugger tries to limit use of a dynamic memory
- allocations the code which reserves szadb work screen and
- necessary buffers does that in a "false" program space and
- is located in start.s. Should you decide to modify it for any
- reasons look for comments which attempt to describe what
- really happens.
- Note: despite of the fact that szadb can be used on TT the
- version 1.4 is still ST debugger in that sense that it does not
- support yet any of 68020/30 specific codes. This should be
- fine for most programs in the nearest future. An expansion
- will be easy and straightforward provided you will have
- necessary reference handy.
-
-
-
- 5.4 Customization
-
-
- Some possible customizations were already mentioned. The
- other obvious one is a version of szadb without on-line help.
- If you feel brave enough remove the definition of the compile
- time constant HELP from the makefile. A size of the
- executables will undoubtely go down.
- In order to create a version in some other language edit a
- file lang.h. It contains all messages which szadb may
- display.
- You can adjust to your taste some other points. For example,
- what are default requests attached to stepping commands and
- what is their status (look in stepping.c for bpstat(),
- findcmds(), bpt_list[]). Which characters are used for
- requests switching (see getrequs() in pcs.c). Some features,
- like support for functions keys or other symbol table formats,
- can be taken out easily without affecting the whole design.
- If you try to recreate szadb with another compiler you should
- note that essential parts of this program were written in
- assembler and may have to be translated to something your
-
-
-
- 24
-
-
-
-
- tools can accept. Here is another point to watch for. A
- variable _BLKSIZ sets size of Malloc'ed blocks. If a library
- you use supports something similar modify accordingly. There
- are also some constructs in C code, like a static
- initialization of a union member (bpt_list in stepping.c) and
- an array of size 0 in a definition of struct symbol in adb.h,
- which are accepted by Szozobon C but can give a hiccup to some
- other compilers. These points can be modified without undue
- strain. Otherwise the code should be pretty portable,
- although it is ST specific by its very nature.
-
-
-
- 5.5 Running on a verge
-
-
- You may find yourself in a situation when your program wants
- all memory it can get and together with the debugger does not
- exactly fits into available space. There are still some
- things which can be done.
- Keep in mind that szadb grabs all memory it needs before a
- program to debug is loaded and it does not make any claims
- later. These requirements can be minimized. Function key
- definitions if non-existent will not use memory at all,
- discounting the supporting code. This code by itself is
- mostly contained in a file fkeydefs.c and it is easy to
- remove. The flag -nc, for no commands, gives some memory for
- a price of missing breakpoint requests. A more substantial
- memory chunk can be released with -nb, for no buffering on
- transcript, flag. You still can open a transcript file but
- all output will be direct. Beware of GEMDOS when using
- transcripts without buffering.
-
- If this does not help then there is a time to trim some fat
- from szadb itself. You will have to recompile it leaving some
- features out. On-line help is probably the first candidate.
- All this effort can be wasted if you will forget about one
- thing. Due to an infamous design bug in TOS a Malloc system
- call can be invoked only a small fixed number of times. When
- this pool is exhausted you will get "out of memory condition"
- even if memory is still plentiful. Therefore all allocation
- functions, from smart libraries, request a memory from
- the system in bigger pieces and later try to satisfy all
-
-
-
- 25
-
-
-
-
- requests chopping from an already owned resource. The name of
- the game for szadb is to use for all its needs only one chunk
- of a system memory which is just big enough, so not too much
- of an unused memory will be left. The whole symbol table of a
- debugged program must fit there and all szadb requests for a
- space for internal structures have to be statisfied. To
- adjust sizes properly you may want to change a constant CHUNK
- which is defined at the top of a file adb.c.
- If everything else fail you may still try to change a value of
- a global variable __STKSIZ from start.s but this would be
- probably the last stand.
-
-
-
- 5.6 Writing to memory
-
-
- It can be done. This is left as an exercise to the reader.
- Check your documentation.
-
-
-
- 26
-
-
-
-
- Contents
-
-
- 1 Introduction 1
-
-
- 2 First steps 2
- 2.1 Starting . . . . . . . . . . . . . . . . . . . . . . . 2
- 2.2 Where am I? . . . . . . . . . . . . . . . . . . . . . . 3
- 2.3 Disassembling . . . . . . . . . . . . . . . . . . . . . 4
- 2.4 More on talking to szadb . . . . . . . . . . . . . . . 5
-
-
- 3 Running under szadb 7
- 3.1 How to run --- with arguments . . . . . . . . . . . . . 7
- 3.2 Setting breakpoints . . . . . . . . . . . . . . . . . . 8
- 3.3 Displaying information . . . . . . . . . . . . . . . . . 9
- 3.4 Recording your session . . . . . . . . . . . . . . . . . 10
-
-
- 4 Bug hunting 11
- 4.1 Compiling for szadb . . . . . . . . . . . . . . . . . . 11
- 4.2 The first bug . . . . . . . . . . . . . . . . . . . . . 13
- 4.3 . .a.nd the other one . . . . . . . . . . . . . . . . . 14
- 4.4 Breaking out . . . . . . . . . . . . . . . . . . . . . . 15
-
-
- 5 More fun and games 17
- 5.1 Advanced steps . . . . . . . . . . . . . . . . . . . . . 17
- 5.2 How to use function keys . . . . . . . . . . . . . . . . 18
- 5.3 Other symbol table formats . . . . . . . . . . . . . . . 20
- 5.3.1 Mark Williams C support . . . . . . . . . . . . . 20
- 5.3.2 How to work with gcc . . . . . . . . . . . . . . 21
- 5.3.3 Command line interpretation . . . . . . . . . . . 22
- 5.3.4 Other compilers . . . . . . . . . . . . . . . . . 23
- 5.3.5 Screens of not a standard ST size . . . . . . . . 23
- 5.4 Customization . . . . . . . . . . . . . . . . . . . . . 24
- 5.5 Running on a verge . . . . . . . . . . . . . . . . . . . 25
- 5.6 Writing to memory . . . . . . . . . . . . . . . . . . . 26
-
-
-
- i
-